using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Windows.Forms;



namespace Crm2011.Framework.Connect
{
    public class ErrorProviderCollection : Dictionary<Control, ErrorProvider>
    {
        public ErrorProviderCollection(ContainerControl containerControl)
        {
            _parentControl = containerControl;
        }



        private readonly ContainerControl _parentControl;



        public void ClearAllErrors()
        {
            foreach (ErrorProvider previousError in base.Values)
            {
                previousError.Clear();
            }
            base.Clear();
        }



        /// <summary>
        /// Reset (make invisible) an error errMessage that is displayed with a control.
        /// </summary>
        /// <param name="control"></param>
        public void ClearError(Control control)
        {
            if (!base.ContainsKey(control)) return; // nothing to do
            base[control].SetError(control, "");
        }



        /// <summary>
        /// Display an error errMessage right of a control.
        /// </summary>
        /// <param name="control"></param>
        /// <param name="message"></param>
        public void SetError(Control control, string message)
        {
            // If there's not yet an ErrorProvider for that control,
            // create a new ErrorProvider and add it to the dictionary.
            if (!base.ContainsKey(control))
                base.Add(control, newErrorProvider(control));

            base[control].SetError(control, PublicFunc.Wrap(message, 100));
        }



        public void SetError(string controlTag, string message)
        {
            Control control = findControl(_parentControl.Controls, controlTag);
            Debug.Assert(control != null, string.Format("No control found for Tag {0}", controlTag));
            this.SetError(control, message);
        }



        public void SetError(DataColumn boundColumn, string message)
        {
            Control control = findControl(_parentControl.Controls, boundColumn);
            Debug.Assert(control != null, string.Format("No control found for DataColumn {0}", boundColumn));
            this.SetError(control, message);
        }



        private Control findControl(Control.ControlCollection controls, DataColumn boundColumn)
        {
            Control retVal = null;
            foreach (Control control in controls)
            {
                // check current control
                foreach (Binding binding in control.DataBindings)
                {
                    if (binding.BindingMemberInfo.BindingMember == boundColumn.ColumnName)
                    {
                        retVal = control;
                        break; // for
                    }
                }

                // only check childs if the current control is not the bound control!
                if (retVal != null) break; // for

                // dive into child controls
                if (control.Controls.Count > 0)
                    retVal = findControl(control.Controls, boundColumn);

                if (retVal != null) break; // for
            }
            return retVal;
        }



        private Control findControl(IEnumerable controls, string tag)
        {
            Control retVal = null;
            foreach (Control control in controls)
            {
                // check current control
                if (control.Tag != null && control.Tag.ToString().Equals(tag, StringComparison.OrdinalIgnoreCase))
                {
                    retVal = control;
                    break; // for
                }

                // dive into child controls
                if (control.Controls.Count > 0)
                    retVal = findControl(control.Controls, tag);

                if (retVal != null) break; // for
            }
            return retVal;
        }



        private ErrorProvider newErrorProvider(Control control)
        {
            ErrorProvider errorProvider1 = new ErrorProvider();
            ((ISupportInitialize) (errorProvider1)).BeginInit();
            errorProvider1.SetIconAlignment(control, ErrorIconAlignment.MiddleRight);
            errorProvider1.SetIconPadding(control, 2);
            errorProvider1.BlinkStyle = ErrorBlinkStyle.AlwaysBlink;
            errorProvider1.ContainerControl = _parentControl;
            ((ISupportInitialize) (errorProvider1)).EndInit();
            return errorProvider1;
        }
    }
}